/*
  浏览器JS事件循环机制（JS事件轮询机制）
    是JS异步代码的执行机制
    
    主线程将全局所有代码放入执行栈中执行，遇到同步代码从上到下依次执行，遇到异步代码交给浏览器相应的模块管理：
      比如：
        遇到定时器，定时器函数会被同步调用，
        将回调函数和时间交给浏览器定时器管理模块管理，于此同时主线程继续执行剩下代码
        而浏览器定时器管理模块负责计时，到点时候会将回调函数添加到回调队列中

        遇到DOM事件，将事件和回调函数交给浏览器DOM管理模块管理，于此同时主线程继续执行剩下代码
        而浏览器DOM管理模块负责绑定事件，当用户触发事件，将回调函数添加到回调队列中

    当主线程执行完全局所有代码时，开启事件轮询（事件循环 event loop）, 遍历回调队列，取出回调函数，依次同步执行
    等执行完所有回调函数，过一段时间又会继续事件循环
      
    
    回调队列分为两种队列：宏任务队列和微任务队列
    
      微任务队列
        promise.then / catch / finally 的回调函数
        async / await (await后面的内容)
        MutationObserver(监视DOM元素变化)

      宏任务队列
        setTimeout / setInterval
        ajax
        DOM事件回调函数

    微任务队列执行优先级高，宏任务队列执行优先级低。
    当主线程开启事件轮询，先执行微任务队列中回调函数，等所有函数都执行完了。
    才会执行宏任务队列的回调函数，执行一个宏任务队列的回调函数，又会执行微任务队列中所有回调函数
    如果微任务队列中没有回调函数或执行完毕，才会执行下一个宏任务队列的回调函数，以此类推

  NodeJS事件轮询机制：
    https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick
    Koa 洋葱模型
*/

console.log(1);

setTimeout(() => {
  console.log(2);
  const p = new Promise((resolve) => {
    console.log(3);
    resolve();
  });

  p.then(() => {
    console.log(4);
  });
}, 0);

setTimeout(() => {
  console.log(5);
  const p = new Promise((reject, resolve) => {
    // 第一个参数就是resolve
    console.log(6);
    reject();
  });

  p.then(
    () => {
      console.log(7);
    },
    () => {
      console.log(8);
    }
  );
}, 0);

Promise.resolve().then(() => {
  console.log(9);
});

Promise.resolve().then(() => {
  console.log(10);
});

console.log(11);

/*
  第一阶段：（先执行同步代码，在执行异步代码）
    1 11
      微任务队列：[p1, p2]
      宏任务队列：[s1, s2]

  第二阶段：先执行微任务队列中所有回调函数
    1 11 9 10
      微任务队列：[]
      宏任务队列：[s1, s2]
  
  第三阶段：微任务队列执行完了，接着执行宏任务队列第一个回调
    1 11 9 10 2 3
      微任务队列：[p3]
      宏任务队列：[s2]
  
  第四阶段：执行一个宏任务，接着执行微任务
    1 11 9 10 2 3 4
      微任务队列：[]
      宏任务队列：[s2]

  第五阶段：微任务队列执行完了，接着执行宏任务队列第一个回调
    1 11 9 10 2 3 4 5 6
      微任务队列：[P4]
      宏任务队列：[]

  第六阶段：执行一个宏任务，接着执行微任务
    1 11 9 10 2 3 4 5 6 7
*/
